/*
 * LeafNodeSerializer.h
 *
 *  Created on: Nov 1, 2012
 *      Author: m
 */

#ifndef LEAFNODESERIALIZER_H_
#define LEAFNODESERIALIZER_H_

#include "../../../physical_layer/physical_layer.h"
#include "../bplusnodes/NewLeaf.h"
#include "LeafRegisterSerializer.h"
#include "BPlusTreeDefinitions.h"
#include <cassert>

using physical::byte;
using physical::byteStream;

class LeafNodeSerializer: public physical::VariableSizeRecordSerializer< LeafSerializationBlock >
{
private:
    typedef physical::ListSerializer< LeafRegister_t > list_serializer_t;

private:
    list_serializer_t::_T_Serializer_ptr m_registerSerializer;
    list_serializer_t                    m_contentSerializer;

public:
    LeafNodeSerializer() :
        m_registerSerializer( new LeafRegisterSerializer ),
        m_contentSerializer( m_registerSerializer )
    {
    }

    ~LeafNodeSerializer()
    {
    }

    size_t serialize( const _T &element, byteStream block )
    {
        size_t bytesUsed = 0;
        byte* blockPtr = block;
        size_t totalBytesUsed = 0;

        assert( element.level == 0 );

        ( (LeafRegisterSerializer*) m_registerSerializer.get() )->resetKey();

        // Persisto el nivel del nodo
        memcpy( blockPtr, &element.level, sizeof(NodeLevel_t) );
        bytesUsed = sizeof(NodeLevel_t);
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        // Persisto el NodeID del hermano derecho
        memcpy( blockPtr, &element.rightSibling, sizeof(NodeID_t) );
        bytesUsed = sizeof(NodeID_t);
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        // Persisto la lista de contenido
        bytesUsed = m_contentSerializer.serialize( element.content, blockPtr );
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        return totalBytesUsed;
    }

    size_t deserialize( const byteStream block, _T &element )
    {
        size_t bytesUsed = 0;
        size_t totalBytesUsed = 0;
        byte* blockPtr = (byte*)block;

        ( (LeafRegisterSerializer*) m_registerSerializer.get() )->resetKey();

        // deserializo el nivel del nodo
        memcpy( &element.level, blockPtr, sizeof(NodeLevel_t) );
        bytesUsed = sizeof(NodeLevel_t);
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        // deserializo el NodeID del hermano derecho
        memcpy( &element.rightSibling, blockPtr, sizeof(NodeID_t) );
        bytesUsed = sizeof(NodeID_t);
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        // deserializo la lista de contenido
        bytesUsed = m_contentSerializer.deserialize( blockPtr, element.content );
        totalBytesUsed += bytesUsed;
        blockPtr += bytesUsed;

        return totalBytesUsed;
    }

    size_t computeSize( const _T &element )
    {
        size_t totalBytesUsed = 0;

        ( (LeafRegisterSerializer*) m_registerSerializer.get() )->resetKey();

        totalBytesUsed += sizeof(NodeLevel_t);

        totalBytesUsed += sizeof(NodeID_t);

        totalBytesUsed += m_contentSerializer.computeSize( element.content );

        return totalBytesUsed;
    }

    // Interfáz dinámica
    size_t serialize( const _T_ptr &elementPtr, byteStream block )
    {
        return this->serialize( *elementPtr, block );
    }

    size_t deserialize( const byteStream block, _T_ptr &elementPtr )
    {
        elementPtr.reset( new _T );
        return this->deserialize( block, *elementPtr );
    }

    size_t computeSize( const _T_ptr &elementPtr )
    {
        return this->computeSize( *elementPtr );
    }
};

#endif /* LEAFNODESERIALIZER_H_ */
